﻿/*
 * Erstellt mit SharpDevelop.
 * Benutzer: Kai Patrick
 * Datum: 24.03.2008
 * Zeit: 16:20
 * 
 * Sie können diese Vorlage unter Extras > Optionen > Codeerstellung > Standardheader ändern.
 */

using System;
using System.Collections.Generic;
using Gamadus.Engine.Compiler.Ast;
using Irony.Compiler;
using Microsoft.Scripting;
using MSAst = Microsoft.Scripting.Ast;

namespace Gamadus.Engine.Compiler
{
	/// <summary>
	/// Main class
	/// </summary>
	public class Compiler
	{
		/// <summary>
		/// Litte helper function for Parser Test app
		/// </summary>
		/// <param name="source"></param>
		/// <returns></returns>
		public static ParserResults Parse(string source)
		{
			LanguageCompiler compiler = new LanguageCompiler(new GmlGrammar());
			//SourceFile source = new SourceFile("show_message(\"hallo\")", "source", 8);
        	AstNode rootNode = compiler.Parse(source+"\n");
        	return new ParserResults(compiler, rootNode);
		}
		
		public static MSAst.LambdaExpression Compile(string code)
		{
			string source = code;
			
			Console.WriteLine(source);
			Console.WriteLine("--------------------------------------------------------------------------------");
			
			Runtime.RuntimeMgr.Instance.Init();
			LanguageCompiler compiler = new LanguageCompiler(new GmlGrammar());
			AstNode rootNode = compiler.Parse(source+"\n");
			ParserResults results = new ParserResults(compiler, rootNode);
			if(results.Errors.Count > 0)
				return null;
			
			
			WriteNode(results.RootNode);
			Console.WriteLine("--------------------------------------------------------------------------------");
			
			if(rootNode.Term.Name != "Prog")
				throw new ArgumentException("Expected Prog as root node");
			AstNode listNode = rootNode.ChildNodes[0];
			if(listNode.Term.Name != "Statement*")
				throw new ArgumentException("Expected Statement* after Prog");
			StatementList root = new StatementList(listNode);
			
			MSAst.Expression body = root.Generate();
			
			return Runtime.RuntimeMgr.Instance.Finish(body);
			
        }
		
		static void WriteNode(AstNode node)
		{
			WriteNode(node, 0);
		}
		
		static void WriteNode(AstNode node,int depth)
		{
			Console.WriteLine(RepeatString("  ",depth)+node.ToString());
			foreach(AstNode child in node.ChildNodes)
			{
				WriteNode(child, depth+1);
			}
		}
		static string RepeatString(string str, int num)
		{
			string ret = "";
			for(int i = 0; i < num; i++)
			{
				ret += str;
			}
			return ret;
		}
		
	}
}
